package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"time"

	log "github.com/sirupsen/logrus"
)

type SavePoint struct {
	Time  time.Time            `json:"time,omitempty"`
	Ships map[string]time.Time `json:"ships,omitempty"`
}

type SavePointHandle struct {
	path      string
	savePoint SavePoint
}

func NewSavePointHandle(path string) (*SavePointHandle, error) {
	f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644)
	if err != nil {
		return nil, err
	}
	defer f.Close() // nolint
	content, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}
	if len(content) == 0 {
		sph := SavePointHandle{
			path: path,
			savePoint: SavePoint{
				Ships: map[string]time.Time{},
			},
		}
		return &sph, nil
	}
	var sp SavePoint
	err = json.Unmarshal(content, &sp)
	if err != nil {
		return nil, err
	}
	sph := SavePointHandle{
		path:      path,
		savePoint: sp,
	}
	return &sph, nil
}

func (h *SavePointHandle) GetStartTime(mmsi int) *time.Time {
	str := fmt.Sprintf("%d", mmsi)
	if t, ok := h.savePoint.Ships[str]; ok {
		return &t
	}
	return nil
}

func (h *SavePointHandle) UpdateStartTime(mmsi int, startTime time.Time) error {
	str := fmt.Sprintf("%d", mmsi)
	h.savePoint.Time = time.Now()
	h.savePoint.Ships[str] = startTime
	return nil
}

func (h *SavePointHandle) Persist() error {
	back := fmt.Sprintf("%s.%s", h.path, "bak")
	err := os.Rename(h.path, back)
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Error("failed backup save point file")
	}
	b, err := json.Marshal(h.savePoint)
	if err != nil {
		return err
	}
	f, err := os.Create(h.path)
	if err != nil {
		return err
	}
	_, err = f.Write(b)
	return err
}
